/*------------------------------------------------------------------------
*
* geqo_px.c
*
* 位置交叉 [PX] 例程；
* PX 运算符根据 Syswerda
* (The Genetic Algorithms Handbook, L Davis, ed)
*
* src/backend/optimizer/geqo/geqo_px.c
*
*-------------------------------------------------------------------------
*/

/* 贡献者：
   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
   *  Martin Utesch				 * 自动控制研究所		   *
   =							 = 矿业与技术大学 =
   *  utesch@aut.tu-freiberg.de  * 德国弗赖贝格				   *
   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
 */

/* px 算法源于 Genitor : */
/*************************************************************/
/*															 */
/*	Copyright (c) 1990										 */
/*	Darrell L. Whitley										 */
/*	计算机科学系									         */
/*	科罗拉多州立大学									     */
/*															 */
/*	特此允许复制本程序的全部或部分以进行自由分发。作者的姓名  */
/*	及本版权声明必须包含在任何复制中。 */
/* geqo_copy
 *
 *	 将一个基因复制到另一个
 *
 */
/*															 */
/*************************************************************/

#include "postgres.h"
#include "optimizer/geqo_random.h"
#include "optimizer/geqo_recombination.h"

#if defined(PX)

/* px
 *
 * 位置交叉
 */
void px(PlannerInfo *fc_root, Gene *fc_tour1, Gene *fc_tour2, Gene *fc_offspring, int fc_num_gene,
   City * fc_city_table)
{
	int			fc_num_positions;
	int			fc_i,
				fc_pos,
				fc_tour2_index,
				fc_offspring_index;

	/* 初始化城市表 */
	for (fc_i = 1; fc_i <= fc_num_gene; fc_i++)
		fc_city_table[fc_i].used = 0;

	/* 选择将直接从父代继承的随机位置 */
	fc_num_positions = geqo_randint(fc_root, 2 * fc_num_gene / 3, fc_num_gene / 3);

	/* 选择随机位置 */
	for (fc_i = 0; fc_i < fc_num_positions; fc_i++)
	{
		fc_pos = geqo_randint(fc_root, fc_num_gene - 1, 0);

		fc_offspring[fc_pos] = fc_tour1[fc_pos];	/* 将城市转移到子代 */
		fc_city_table[(int) fc_tour1[fc_pos]].used = 1;	/* 标记已使用的城市 */
	}

	fc_tour2_index = 0;
	fc_offspring_index = 0;


	/* px 主要部分 */

	while (fc_offspring_index < fc_num_gene)
	{

		/* 子代中的下一个位置已填充 */
		if (!fc_city_table[(int) fc_tour1[fc_offspring_index]].used)
		{

			/* tour1 中的下一个城市未使用 */
			if (!fc_city_table[(int) fc_tour2[fc_tour2_index]].used)
			{

				/* 从 tour1 继承 */
				fc_offspring[fc_offspring_index] = fc_tour2[fc_tour2_index];

				fc_tour2_index++;
				fc_offspring_index++;
			}
			else
			{					/* tour2 中的下一个城市已被使用 */
				fc_tour2_index++;
			}
		}
		else
		{						/* 子代中的下一个位置已填充 */
			fc_offspring_index++;
		}
	}
}

#endif							/* defined(PX) */
